package com.gdsz.libbasic.utils.assist

import java.util.Locale

object HexUtil {
    /**
     * 用于建立十六进制字符的输出的小写字符数组
     */
    private val DIGITS_LOWER = charArrayOf(
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
    )

    /**
     * 用于建立十六进制字符的输出的大写字符数组
     */
    private val DIGITS_UPPER = charArrayOf(
        '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    )

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data byte[]
     * @return 十六进制char[]
     */
    @JvmStatic
    fun encodeHex(data: ByteArray): CharArray {
        return encodeHex(data, true)
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data        byte[]
     * @param toLowerCase `true` 传换成小写格式 ， `false` 传换成大写格式
     * @return 十六进制char[]
     */
    @JvmStatic
    fun encodeHex(data: ByteArray, toLowerCase: Boolean): CharArray {
        return encodeHex(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
    }

    /**
     * 将字节数组转换为十六进制字符数组
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制char[]
     */
    @JvmStatic
    fun encodeHex(data: ByteArray, toDigits: CharArray): CharArray {
        val l = data.size
        val out = CharArray(l shl 1)
        // two characters form the hex value.
        var i = 0
        var j = 0
        while (i < l) {
            out[j++] = toDigits[0xF0 and data[i].toInt() ushr 4]
            out[j++] = toDigits[0x0F and data[i].toInt()]
            i++
        }
        return out
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data byte[]
     * @return 十六进制String
     */
    @JvmStatic
    fun encodeHexStr(data: ByteArray): String {
        return encodeHexStr(data, false)
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data        byte[]
     * @param toLowerCase `true` 传换成小写格式 ， `false` 传换成大写格式
     * @return 十六进制String
     */
    @JvmStatic
    fun encodeHexStr(data: ByteArray, toLowerCase: Boolean): String {
        return encodeHexStr(data, if (toLowerCase) DIGITS_LOWER else DIGITS_UPPER)
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param data     byte[]
     * @param toDigits 用于控制输出的char[]
     * @return 十六进制String
     */
    @JvmStatic
    fun encodeHexStr(data: ByteArray, toDigits: CharArray): String {
        return String(encodeHex(data, toDigits))
    }


    /**
     * 2进制转16进制
     * @param binary
     * @return
     */
    @JvmStatic
    fun toHexString(binary: String): String {
        if (binary.isEmpty() || binary.length % 8 != 0) return ""
        val hex = StringBuilder()
        var iTmp: Int
        var i = 0
        while (i < binary.length) {
            iTmp = 0
            for (j in 0..3) {
                iTmp += binary.substring(i + j, i + j + 1).toInt() shl 4 - j - 1
            }
            hex.append(Integer.toHexString(iTmp))
            i += 4
        }
        return hex.toString()
    }

    /**
     * 将十六进制字符数组转换为字节数组
     *
     * @param data 十六进制char[]
     * @return byte[]
     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度，将抛出运行时异常
     */
    @JvmStatic
    fun decodeHex(data: CharArray): ByteArray {
        val len = data.size
        if (len and 0x01 != 0) {
            throw RuntimeException("Odd number of characters.")
        }
        val out = ByteArray(len shr 1)

        // two characters form the hex value.
        var i = 0
        var j = 0
        while (j < len) {
            var f: Int = toDigit(data[j], j) shl 4
            j++
            f = f or toDigit(data[j], j)
            j++
            out[i] = (f and 0xFF).toByte()
            i++
        }
        return out
    }

    /**
     * 将十六进制字符转换成一个整数
     *
     * @param ch    十六进制char
     * @param index 十六进制字符在字符数组中的位置
     * @return 一个整数
     * @throws RuntimeException 当ch不是一个合法的十六进制字符时，抛出运行时异常
     */
    @JvmStatic
    fun toDigit(ch: Char, index: Int): Int {
        val digit = ch.digitToIntOrNull(16) ?: -1
        if (digit == -1) {
            throw java.lang.RuntimeException(
                "Illegal hexadecimal character " + ch
                        + " at index " + index
            )
        }
        return digit
    }

    /**
     * 十六进制字符串装十进制
     *
     * @param hex 十六进制字符串
     * @return 十进制数值
     */
    @JvmStatic
    fun hexStringToAlgorism(hex: String): Int {
        val hexString = hex.uppercase(Locale.getDefault())
        val max = hexString.length
        var result = 0
        for (i in max downTo 1) {
            val c = hexString[i - 1]
            val algorism: Int = if (c in '0'..'9') {
                c - '0'
            } else {
                c - '7' // 'A' 对应的 ASCII 值为 65，因此减去 '7' 转为对应的十进制值
            }
            result += Math.pow(16.0, (max - i).toDouble()).toInt() * algorism
        }
        return result
    }

    /**
     * 十六转二进制
     *
     * @param hex 十六进制字符串
     * @return 二进制字符串
     */
    @JvmStatic
    fun hexStringToBinary(hex: String): String {
        val hexString = hex.uppercase(Locale.getDefault())
        var result = ""
        val max = hexString.length
        for (i in 0 until max) {
            val c = hexString[i]
            result += when (c) {
                '0' -> "0000"
                '1' -> "0001"
                '2' -> "0010"
                '3' -> "0011"
                '4' -> "0100"
                '5' -> "0101"
                '6' -> "0110"
                '7' -> "0111"
                '8' -> "1000"
                '9' -> "1001"
                'A' -> "1010"
                'B' -> "1011"
                'C' -> "1100"
                'D' -> "1101"
                'E' -> "1110"
                'F' -> "1111"
                else -> ""
            }
        }
        return result
    }


    /**
     * 二进制字符串转十进制
     *
     * @param binary 二进制字符串
     * @return 十进制数值
     */
    @JvmStatic
    fun binaryToAlgorism(binary: String): Int {
        val max = binary.length
        var result = 0
        for (i in max downTo 1) {
            val c = binary[i - 1]
            val algorism = c - '0'
            result += Math.pow(2.0, (max - i).toDouble()).toInt() * algorism
        }
        return result
    }

    /**
     * 十六进制字符串转为Byte数组,每两个十六进制字符转为一个Byte
     *
     * @param hex 十六进制字符串
     * @return byte 转换结果
     */
    @JvmStatic
    fun hexStringToByte(hex: String): ByteArray {
        val max = hex.length / 2
        val bytes = ByteArray(max)
        val binarys = hexStringToBinary(hex)
        for (i in 0 until max) {
            bytes[i] = binaryToAlgorism(binarys.substring(i * 8 + 1, (i + 1) * 8)).toByte()
            if (binarys[8 * i] == '1') {
                bytes[i] = (0 - bytes[i]).toByte()
            }
        }
        return bytes
    }

    /**
     * 十六进制串转化为byte数组
     *
     * @return the array of byte
     */
    @JvmStatic
    fun hexToByte(hex: String): ByteArray {
        if (hex.length % 2 != 0) {
            throw IllegalArgumentException()
        }
        val arr = hex.toCharArray()
        val b = ByteArray(hex.length / 2)
        for (i in hex.indices step 2) {
            val swap = "" + arr[i] + arr[i + 1]
            val byteint = Integer.parseInt(swap, 16) and 0xFF
            b[i / 2] = byteint.toByte()
        }
        return b
    }

    /**
     * 字节数组转换为十六进制字符串
     *
     * @param b ByteArray 需要转换的字节数组
     * @return String 十六进制字符串
     */
    @JvmStatic
    fun byte2hex(b: ByteArray): String {

        var hs = ""
        var stmp: String
        for (n in b.indices) {
            stmp = Integer.toHexString(b[n].toInt() and 0xff)
            hs += if (stmp.length == 1) {
                "0$stmp"
            } else {
                stmp
            }
        }
        return hs.uppercase(Locale.getDefault())

    }

    /**
     * 字节数组转换为十六进制字符串
     *
     * @param bytes ByteArray 需要转换的字节数组
     * @return String 十六进制字符串
     */
    @JvmStatic
    fun byteArrayToHex2(bytes: ByteArray): String {
        val result = StringBuilder()
        for (index in bytes.indices) {
            val invalue1 = Integer.toHexString((bytes[index].toInt() shr 4) and 0xF)
            val intValue2 = Integer.toHexString(bytes[index].toInt() and 0xF)
            result.append(intValue2)
        }
        return result.toString()
    }

    /**
     * 字符串转换成十六进制字符串
     *
     * @param str 待转换的ASCII字符串
     * @return String 每个Byte之间空格分隔，如: [61 6C 6B]
     */
    @JvmStatic
    fun str2HexStr(str: String): String {
        val chars = "0123456789ABCDEF".toCharArray()
        val sb = StringBuilder("")
        val bs = str.toByteArray()
        var bit: Int

        for (i in bs.indices) {
            bit = (bs[i].toInt() and 0x0f0) shr 4
            sb.append(chars[bit])
            bit = bs[i].toInt() and 0x0f
            sb.append(chars[bit])
            sb.append(' ')
        }
        return sb.toString().trim()
    }

    /**
     * 十六进制转换字符串
     *
     * @param hexStr str Byte字符串(Byte之间无分隔符 如:[616C6B])
     * @return String 对应的字符串
     */
    @JvmStatic
    fun hexStr2Str(hexStr: String): String {
        val str = "0123456789ABCDEF"
        val hexs = hexStr.toCharArray()
        val bytes = ByteArray(hexStr.length / 2)
        var n: Int

        for (i in bytes.indices) {
            n = str.indexOf(hexs[2 * i]) * 16
            n += str.indexOf(hexs[2 * i + 1])
            bytes[i] = (n and 0xff).toByte()
        }
        return String(bytes)
    }

    /**
     * bytes转换成十六进制字符串
     *
     * @param b ByteArray
     * @return String 每个Byte值之间空格分隔
     */
    @JvmStatic
    fun byte2HexStr(b: ByteArray): String {
        var stmp: String
        val sb = StringBuilder("")
        for (n in b.indices) {
            stmp = Integer.toHexString(b[n].toInt() and 0xFF)
            sb.append(if (stmp.length == 1) "0$stmp" else stmp)
            sb.append(" ")
        }
        return sb.toString().uppercase(Locale.getDefault()).trim()
    }

    /**
     * bytes字符串转换为Byte值
     *
     * @param src Byte字符串，每个Byte之间没有分隔符
     * @return ByteArray
     */
    @JvmStatic
    fun hexStr2Bytes(src: String): ByteArray {
        var m: Int
        var n: Int
        val l = src.length / 2
        val ret = ByteArray(l)
        for (i in 0 until l) {
            m = i * 2 + 1
            n = m + 1
            ret[i] = src.substring(i * 2, m).toByte(16)
        }
        return ret
    }

    /**
     * 将十进制转换为指定长度的十六进制字符串
     *
     * @param algorism   Int 十进制数字
     * @param maxLength  Int 转换后的十六进制字符串长度
     * @return String 转换后的十六进制字符串
     */
    @JvmStatic
    fun algorismToHEXString(algorism: Int, maxLength: Int): String {
        var result = Integer.toHexString(algorism)

        if (result.length % 2 == 1) {
            result = "0$result"
        }
        return patchHexString(result.uppercase(Locale.getDefault()), maxLength)
    }


    /**
     * HEX字符串前补0，主要用于长度位数不足。
     *
     * @param str       String 需要补充长度的十六进制字符串
     * @param maxLength Int 补充后十六进制字符串的长度
     * @return 补充结果
     */
    @JvmStatic
    fun patchHexString(str: String, maxLength: Int): String {
        var temp = ""
        for (i in 0 until maxLength - str.length) {
            temp = "0$temp"
        }
        return (temp + str).substring(0, maxLength)
    }


    //    // 校验位计算，取低8位为校验位
    @JvmStatic
    fun checkDigit(num: Int): String? {
        var sum = num
        val checkSumBinary = Integer.toBinaryString(sum)
        var checkSum = ""
        if (checkSumBinary.length > 8) {
            checkSum = checkSumBinary.substring(checkSumBinary.length - 8, checkSumBinary.length)
            sum = checkSum.toInt(2)
        } else {
            sum = checkSumBinary.toInt(2)
        }


        return Integer.toHexString(sum)
    }


    @JvmStatic
    fun int2HexByte(num: Int): Byte {
        val hexInt = num.toString(16).toInt(16)
        return hexInt.toByte()
    }
}